Skip to content

v0.6.80: security hardening, nextjs minor version bump, cloudwatch tools, seo fixes#4608

Merged
waleedlatif1 merged 12 commits into
mainfrom
staging
May 15, 2026
Merged

v0.6.80: security hardening, nextjs minor version bump, cloudwatch tools, seo fixes#4608
waleedlatif1 merged 12 commits into
mainfrom
staging

Conversation

@waleedlatif1
Copy link
Copy Markdown
Collaborator

@waleedlatif1 waleedlatif1 commented May 15, 2026

TheodoreSpeaks and others added 9 commits May 14, 2026 12:54
… tx (#4593)

* v0.6.29: login improvements, posthog telemetry (#4026)

* feat(posthog): Add tracking on mothership abort (#4023)

Co-authored-by: Theodore Li <[email protected]>

* fix(login): fix captcha headers for manual login  (#4025)

* fix(signup): fix turnstile key loading

* fix(login): fix captcha header passing

* Catch user already exists, remove login form captcha

* improvement(db): add session statement/lock timeouts; simplify KB doc tx

* fix(knowledge): close soft-delete TOCTOU on KB document insert

Fix the race the bots flagged: KB delete is soft (`deletedAt = now`) so
the FK can't catch a concurrent KB delete between the existence check
and the document insert.

- Add `insertDocumentsIfKbAlive` helper that gates the insert on
  `EXISTS(SELECT 1 FROM knowledge_base WHERE id=$kb AND deleted_at IS NULL)`
  in the same statement via INSERT...SELECT...WHERE EXISTS. Atomic at the
  MVCC snapshot — no transaction, no row lock.
- Use jsonb_to_recordset to declare column types once, avoiding per-param
  casts for nullable columns.
- Wire into both `createDocumentRecords` (bulk) and `createSingleDocument`.
- Keep the upfront KB existence check as a fast-path early-out for the
  common case; the atomic insert is the race guard.

---------

Co-authored-by: Waleed <[email protected]>
Co-authored-by: Siddharth Ganesan <[email protected]>
Co-authored-by: Vikhyath Mondreti <[email protected]>
* fix(seo): use canonical SITE_URL for robots and sitemap

* fix(seo): drop /templates from sitemap and guard robots/sitemap in seo test
* improvement(scheduler): drain in chunks instead of a single capped claim

Replaces the fixed MAX_CRON_CLAIMS (200) with a chunked drain loop:
claim WORKFLOW_CHUNK_SIZE + JOB_CHUNK_SIZE per iteration, process via
Promise.allSettled, repeat until both claim queries return empty or
MAX_TICK_DURATION_MS elapses. Throughput is no longer bounded by a
static per-tick ceiling; it scales until DB or trigger.dev is the
limit. Per-iteration chunk size still bounds row-lock set and fan-out
concurrency.

Extracts processScheduleItem and processJobItem so the loop body stays
readable. Existing claim semantics (FOR UPDATE SKIP LOCKED, lastQueuedAt
as the claim signal, staleness reclaim) are unchanged.

* improvement(scheduler): skip claim once a queue is exhausted and drop workflowUtils non-null assertion

Addresses Greptile review on PR #4578:
- track per-queue exhaustion when a claim returns fewer than CHUNK_SIZE
  rows; subsequent iterations skip the claim query for that queue. Saves
  one DB round-trip per iteration once one queue drains while the other
  is still working.
- narrow workflowUtils to a local const inside the loop body so the
  schedule processing branch only runs when the import has completed.
  Removes the misleading non-null assertion.
…ck get_message ts (#4600)

* fix(integrations): gdrive trashed search, slack blocks-with-file, slack get_message ts

- Google Drive search/list: skip default `trashed = false` when user query
  already specifies a `trashed = ...` predicate, so trashed-file searches work.
- Slack send-message with files: forward `blocks` through to
  `files.completeUploadExternal` so Block Kit renders when files are attached.
- Slack get_message: switch from `conversations.history` (oldest lower-bound
  returned the next message after) to `conversations.replies` with `ts=`
  for exact-match lookup, plus a defensive ts-equality guard and clearer error.

* fix(google_drive): revert list.ts trashed guard — query is plain text, not gdrive syntax

* fix(slack): omit initial_comment when blocks present so Block Kit actually renders on file uploads
…ounds (#4601)

* fix(security): harden file access controls, webhook auth, and input bounds

* fix(security): extend file access checks to remaining tool routes

* fix(logs): address PR review comments on time filter

* fix(logs): set end-time milliseconds to 999 for datetime filter strings

* fix(files): return 404 instead of 500 on file access denial in utility paths

* remove tooltip from resource tabs
* chore(deps): bump next to 16.2.5 for CVE-2026-44578 SSRF fix

* chore(deps): bump next to 16.2.6 for full May 2026 security release coverage
…rage quota coverage (#4605)

* fix(security): supabase rpc path validation, ssh stream byte cap, storage quota coverage

* fix(security): scope execution log writes to owning workflow; add env-var workspace membership guard

Closes two cross-tenant vulnerabilities:

1. Workflow log cross-tenant write (route.ts + logging-session.ts):
   - Route: SELECT before creating LoggingSession to verify executionId belongs
     to the claimed workflowId; reject with 404 if owned by a different workflow.
   - LoggingSession: add workflow_id to all UPDATE/SELECT WHERE clauses
     (raw SQL marker queries, flushAccumulatedCost, loadExistingCost) so
     writes are a no-op if executionId was somehow injected.

2. Env-var workspace membership guard (environment/utils.ts):
   - getPersonalAndWorkspaceEnv now calls checkWorkspaceAccess when workspaceId
     is provided; throws if the userId is not a member, preventing any future
     caller from reading another workspace's decrypted secrets without
     explicit membership verification at the call site.

* fix(security): remove fileSize > 0 quota bypass gate; exempt logs context from quota

* chore: remove extraneous inline comments

* fix(security): scope markExecutionAsFailed UPDATE by workflowId; thread workflowId through HITL callers

* fix(security): add personal credential ownership check in sharepoint site route; scope markExecutionAsFailed by workflowId

* fix: remove logs from user-accessible upload contexts; restore distinct biome .next glob

* fix(sharepoint): migrate site route to authorizeCredentialUse

The previous fix only checked userId equality for personal credentials and
workspace membership (via getUserEntityPermissions) for workspace credentials.
authorizeCredentialUse additionally enforces credentialMember access for
workspace-scoped credentials, matching the standard pattern used by all
other tool selector routes.

* fix(logging): make workflowId required in markExecutionAsFailed

Making workflowId optional left a footgun — future callers could silently
omit it and the WHERE clause would degrade to executionId-only, losing the
cross-tenant scoping guarantee. All callers already supply workflowId, so
making it required (with string | undefined for the middle params to keep
call sites unchanged) closes the gap without touching any caller.

* test(security): add tests for cross-tenant log guard, quota bypass fix, and workflowId scoping

- log/route.test.ts: verifies cross-tenant executionId guard returns 404
  when the execution belongs to a different workflow, and passes for same
  workflow or fresh executions
- multipart/route.test.ts: verifies fileSize:0 no longer bypasses quota
  check and that the logs context is rejected at the endpoint level
- logging-session.test.ts: verifies markExecutionAsFailed scopes by both
  executionId and workflowId, and that the instance method forwards workflowId

* fix(lint): move IconComponent outside ToolInput to fix noNestedComponentDefinitions

* fix(logging): scope completeWithCancellation and completeWithPause reads by workflowId

Both SELECT queries that check execution status before writing a
terminal result were only filtering on executionId. Adds workflowId
to the WHERE clause so all seven reads and writes in LoggingSession
consistently scope by (workflowId, executionId).
@vercel
Copy link
Copy Markdown

vercel Bot commented May 15, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Skipped Skipped May 15, 2026 2:49am

Request Review

@cursor
Copy link
Copy Markdown

cursor Bot commented May 15, 2026

PR Summary

High Risk
Touches security-sensitive authorization and file-download paths across many tool endpoints and modifies scheduled execution draining logic, so regressions could impact data isolation or background job throughput. Also adds new AWS CloudWatch operations that exercise external credentials/permissions.

Overview
Security hardening: Adds a shared assertToolFileAccess/FileAccessDeniedError flow and applies it across many tool routes before downloading user files; tightens internal-auth checks to require userId; adds workflow-scoped guardrails for /api/workflows/[id]/log to prevent cross-tenant executionId reuse; and switches SharePoint site lookup to authorizeCredentialUse. Also adds workspace-access validation when fetching environment variables.

Limits & quota: Enforces storage quota checks for multipart upload initiation across contexts (with exemptions) and disallows logs uploads via the multipart endpoint; bounds SSH read maxSize and adds a streaming byte cap.

New capability: Introduces CloudWatch mute_alarm/unmute_alarm tool endpoints + contracts, and wires them into the CloudWatch block UI/param parsing.

Operational/UI fixes: Refactors schedule execution to claim due schedules/jobs in chunks with a per-tick time budget; fixes robots/sitemap to use SITE_URL (and adds /contact), adds tests to prevent regressions, and updates the date-range picker to support optional time selection and avoid reopen re-render loops; minor logs/resource tab UI tweaks and a Next.js patch bump in apps/docs.

Reviewed by Cursor Bugbot for commit 922de38. Configure here.

Comment thread apps/sim/app/api/tools/slack/utils.ts
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 15, 2026

Greptile Summary

This release bundles a broad security hardening pass, a new CloudWatch mute/unmute feature, scheduler throughput improvements, and a date-picker re-render fix across 87 files.

  • Security: assertToolFileAccess is now enforced before every file download across ~20 tool routes; workflowId added to all LoggingSession WHERE clauses to prevent cross-workflow ID spoofing; WhatsApp verification token comparison switched to safeCompare; debug logs that leaked HMAC secret lengths removed; Supabase RPC function names now validated and URL-encoded; SSH streaming reads are hard-capped; getPersonalAndWorkspaceEnv gates on workspace membership before fetching env rows.
  • CloudWatch: New mute_alarm / unmute_alarm operations backed by DisableAlarmActionsCommand / EnableAlarmActionsCommand; contracts validate region format and cap alarm list at 100 entries.
  • Scheduler: Replaced fixed-max single-batch claim with a chunked drain loop bounded by MAX_TICK_DURATION_MS (3 min), processing schedules in 100-item chunks until exhausted.

Confidence Score: 5/5

The changes are safe to merge — every security fix is narrowly scoped, all markExecutionAsFailed callers were updated for the new required workflowId parameter, and the scheduler refactor maintains the same claim-then-process contract.

The PR is a well-executed security pass. File-ownership checks are consistent across all updated routes, the WhatsApp timing fix is guarded correctly, the SQL raw-string replacement is accurate, and the logging-session WHERE-clause additions cover every query in the class. The CloudWatch feature follows existing tool patterns exactly. No functional regressions were identified.

No files require special attention.

Important Files Changed

Filename Overview
apps/sim/app/api/files/authorization.ts Tightened assertToolFileAccess signature to require non-optional userId: string, removed the now-redundant internal !userId guard, and added FileAccessDeniedError export class.
apps/sim/app/api/files/multipart/route.ts Broadened storage-quota enforcement to cover all non-exempt upload contexts (not just workspace), using the new QUOTA_EXEMPT_STORAGE_CONTEXTS set; removed logs from allowed contexts.
apps/sim/lib/logs/execution/logging-session.ts Added workflowId to all WHERE clauses in cost flush, status reads, marker persistence, and markExecutionAsFailed to prevent cross-workflow ID confusion; updated static method signature to require workflowId.
apps/sim/app/api/workflows/[id]/log/route.ts Added a pre-check that rejects logging if the provided executionId is already associated with a different workflow, preventing cross-workflow log pollution.
apps/sim/app/api/schedules/execute/route.ts Refactored from single-batch claim to a chunked drain loop bounded by MAX_TICK_DURATION_MS (3 min); extracted processScheduleItem and processJobItem as standalone functions for clarity.
apps/sim/lib/webhooks/providers/whatsapp.ts Fixed timing-attack vulnerability: replaced direct === comparison with safeCompare for WhatsApp webhook verification token; verificationToken is guarded as truthy before the call.
apps/sim/tools/supabase/vector_search.ts Added validateDatabaseIdentifier + encodeURIComponent to prevent RPC path traversal when constructing the Supabase REST URL for function names.
apps/sim/app/api/tools/ssh/read-file-content/route.ts Added streaming byte counter to enforce maxBytes cap during SFTP read, destroying the stream early if the file exceeds the limit.
apps/sim/lib/workflows/executor/human-in-the-loop-manager.ts Fixed SQL injection risk: replaced sql.raw(now.toISOString()) with a parameterized binding; also updated markExecutionAsFailed callers to pass workflowId.
apps/sim/components/emcn/components/date-picker/date-picker.tsx Fixed infinite re-render on popover re-open via lazy useState initialization; added showTime prop for HH:mm selection.
apps/sim/tools/cloudwatch/mute_alarm.ts New tool: mute CloudWatch alarm via DisableAlarmActionsCommand; follows existing CloudWatch tool patterns.
apps/sim/app/api/tools/cloudwatch/mute-alarm/route.ts New route for CloudWatch mute alarm; authenticated, validated against awsCloudwatchMuteAlarmContract, properly destroys CloudWatch client in finally block.
apps/sim/lib/environment/utils.ts Added checkWorkspaceAccess guard before fetching workspace environment variables, preventing unauthorized env reads across workspaces.
apps/sim/tools/google_drive/search.ts Fixed trashed-file search: only prepend trashed = false when the user query does not already specify a trashed = predicate.
apps/sim/tools/slack/get_message.ts Switched from conversations.history to conversations.replies for precise message lookup, and added a timestamp mismatch guard.

Reviews (3): Last reviewed commit: "fix(date-picker): eliminate infinite re-..." | Re-trigger Greptile

Comment thread apps/sim/app/api/tools/telegram/send-document/route.ts
Comment thread apps/sim/lib/uploads/shared/types.ts
Comment thread apps/sim/app/api/schedules/execute/route.ts
@waleedlatif1
Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1
Copy link
Copy Markdown
Collaborator Author

@cursor review

Comment thread apps/sim/components/emcn/components/date-picker/date-picker.tsx Outdated
Comment thread apps/sim/app/api/files/multipart/route.ts
…existing selection (#4609)

* docs(uploads): clarify QUOTA_EXEMPT_STORAGE_CONTEXTS logs entry in JSDoc

* fix(date-picker): eliminate infinite re-render on re-open with existing selection

The useEffect that syncs picker state on open had initialStart and
initialEnd — Date objects computed on every render — in its dependency
array. Because Object.is returns false for any two distinct Date
instances, the effect fired on every render when open=true, calling
setRangeStart/setRangeEnd and triggering another render, producing an
infinite loop that crashed the page.

Fix: compute start and end as local variables inside the effect and
use the stable string props (props.startDate, props.endDate) as deps
instead.

Also removes the redundant typeof fileSize === 'number' guard in the
multipart quota check — fileSize is z.number() (required) in the
contract so it can never be undefined at that point.

* refactor(date-picker): comprehensive cleanup and reliable crash fix

The previous fix still had derived Date objects in useEffect deps.
Object.is(new Date(), new Date()) === false, so any Date in deps causes
the effect to run every render, reproducing the infinite loop on
re-open with existing time selection.

Key changes:
- useEffect deps now use only stable primitives (startDate, endDate strings)
  and compute Date values inside the effect — eliminating the loop
- Replace `rest as any` with a FlatDatePickerProps merged type for safe,
  typed destructuring across the discriminated union
- Remove initialStart/initialEnd render-scope variables; compute inline or
  inside effects to keep derivation local to each use site
- Callbacks use destructured props (onChange, onRangeChange, etc.) instead
  of props.x references
- Remove verbose TSDoc on internal callbacks — names are self-documenting
- Preserve all existing JSX structure and CalendarMonth logic unchanged
@waleedlatif1
Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1
Copy link
Copy Markdown
Collaborator Author

@cursor review

Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 922de38. Configure here.

…width (#4611)

* fix(gmail): send emails as multipart/alternative so they render full-width

* fix(gmail): decode &amp; last in htmlToPlainText to avoid double-decoding compound entities

* fix(gmail): encode body parts as base64 and decode numeric HTML entities
Comment thread apps/sim/tools/gmail/utils.ts Fixed
Comment thread apps/sim/tools/gmail/utils.ts Fixed
Comment thread apps/sim/tools/gmail/utils.ts Fixed
Comment thread apps/sim/tools/gmail/utils.ts Fixed
…4613)

* improvement(gmail): replace custom html-to-text regex with html-to-text library

Resolves 4 CodeQL alerts on htmlToPlainText (incomplete tag/entity handling,
unsafe regex backtracking). Delegates to the html-to-text npm package already
used by the outlook polling trigger and the mail/send route.

* improvement(gmail): match outlook selectors config, add nbsp/anchor tests

Aligns html-to-text options with apps/sim/lib/webhooks/polling/outlook.ts:
suppress anchor hrefs when identical to text, drop bare # anchors, skip
img/script/style content. Adds tests for nbsp preservation and anchor
behavior.
@waleedlatif1 waleedlatif1 merged commit 4efe999 into main May 15, 2026
30 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants